using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Week1.world
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Empty : Microsoft.Xna.Framework.DrawableGameComponent
    {

        public world.behavior.DrawableGlobalVars oVars = new behavior.DrawableGlobalVars();

        public Empty(Game game, int instanceCount)
            : base(game)
        {
            oVars.iInstanceCount = instanceCount;
            oVars.oWorld = new Matrix[instanceCount];
            oVars.oPosition = new Vector3[instanceCount];
            oVars.fRotateX = new float[instanceCount];
            oVars.fAngleX = new float[instanceCount];
            oVars.fRotateX = new float[instanceCount];
            oVars.iGridXUnits = new int[instanceCount];
            oVars.iGridYUnits = new int[instanceCount];
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            oVars.oDepthState = new DepthStencilState();
            oVars.oDepthState.DepthBufferEnable = true;

            oVars.oRasterState = new RasterizerState();
            oVars.oRasterState.CullMode = CullMode.CullCounterClockwiseFace;

            if (oVars.iInstanceCount == 0)
            {
                oVars.iInstanceCount = 1;
                oVars.oPosition[0] = new Vector3(0, 0, 0);
                oVars.oWorld[0] = Matrix.CreateWorld(oVars.oPosition[0], Vector3.Forward, Vector3.Up);
                oVars.fRotateX[0] = 0;
            }

            // initialize behavior classes
            for (int iDx = 0; iDx < oVars.iBehaviourCount; iDx++)
            {
                oVars.oBehavior[iDx].initialize(oVars.iBehaviorHandler[iDx], oVars);
            }
         
            base.Initialize();
        }

        /// <summary>
        /// Sets the position of an empty. if there are multiple instances, it sets the position of 1st instance and ignores the rest.
        /// It is mostly used for triggers.
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <param name="Z"></param>
        public void setEmptyPosition(float X, float Y, float Z)
        {
            oVars.oPosition[0] = new Vector3(X, Y, Z);
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            for (int iDx = 0; iDx < oVars.iBehaviourCount; iDx++)
            {
                oVars.oBehavior[iDx].execute(oVars.iBehaviorHandler[iDx], oVars);
            }
            

            base.Update(gameTime);
        }

        public int registerBehavior(int iDx, world.behavior.BehaviorBase behavior, world.behavior.TriggerKey trigger)
        {
            if (iDx < oVars.iBehaviourCount)
            {
                oVars.oBehavior[oVars.iBehaviourCount] = behavior;
                oVars.iBehaviorHandler[oVars.iBehaviourCount] = behavior.getBehaviorHandlerID(oVars);
                behavior.setTrigger(oVars.iBehaviorHandler[oVars.iBehaviourCount], trigger);

                if (iDx < 0)
                    oVars.iBehaviourCount++;
            }

            return oVars.iBehaviorHandler[oVars.iBehaviourCount - 1];
        }

    }
}
